#include "PrivateBusSlave_port.h"
/*
 * 从机私有协议需要提供的外部接口
 * 需要实现这些函数，库内部需要用到
 * 可以通过函数指针提供，也可以通过一下接口函数实现提供
 *
 * 外设：
 * ADC数据采集数据接口
 * INT：开启关闭外部中断接口
 * UART：串口发送数据接口
 * BUSY：总线状态读取函数
 *
 * */
//从机内存四个区的地址占用情况，给主机，用于计算偏移地址。
//0区uint8_t、1区uint8_t、3区uint16_t、4区uint16_t
//线圈寄存器 离散输入寄存器 输入寄存器 保持寄存器
const uint16_t PrivateBus_Memory_Lens[4]={8,0,0,2};
uint16_t PrivateBus_Keep_Reg[2]={9999,4999};
//线圈寄存器 线圈1 线圈2 线圈3 线圈4 线圈5 线圈6 线圈7 线圈
//离散输入寄存器
//输入寄存器
//保持寄存器 自动重装载值ARR 比较输出值CCR

/**
  * @bried  系统重启
  * @note   调用该函数后，MCU重新启动
  * @param  _reset_flash：是否删除配置信息（恢复出厂设置）
  * @retval None
  */
void PB_Reboot(bool _reset_flash){
    if(_reset_flash){

    }
    HAL_NVIC_SystemReset();
}
/**
  * @bried  获取总线模拟引脚 模拟量
  * @note   None
  * @param  None·
  * @retval None
  */
float PB_Get_Bus_Level(void){
    return Get_Bus_Alp();
}
//命令字读写寄存器
/** 
  * @bried  读取线圈寄存器当前状态
  * @note   返回值可用的地址范围为 长度占用的字节数 如 16：2 13：2 8：1等
  * @param  _reg：寄存器地址
  * @param  _len：访问的数量
  * @param  _res：读取寄存器返回的值
  * @retval None
  */
void PB_Port_01(uint16_t _reg,uint16_t _len,uint8_t* _res){
    uint8_t data=Get_GPIO_Ports();
    *_res=(data>>_reg);
}
/**
  * @bried  读取离散输入寄存器状态
  * @note   None
  * @param  _reg：寄存器地址
  * @param  _len：访问的数量
  * @param  _res：读取寄存器返回的值
  * @retval None
  */
void PB_Port_02(uint16_t _reg,uint16_t _len,uint8_t* _res){

}
/**
  * @bried  读取保持寄存器
  * @note   None
  * @param  _reg：寄存器地址
  * @param  _len：访问的数量
  * @param  _res：读取寄存器返回的值
  * @retval None
  */
void PB_Port_03(uint16_t _reg,uint16_t _len,uint8_t* _res){
    if (_reg>1)return;
    uint8_t* reg=(uint8_t*)PrivateBus_Keep_Reg;
    for (int i = 0; i < _len*2; ++i) {
        if (_reg*2+i>4)return;
        _res[i]=reg[_reg*2+i];
    }
}
/**
  * @bried  读取输入寄存器
  * @note   None
  * @param  _reg：寄存器地址
  * @param  _len：访问的数量
  * @param  _res：读取寄存器返回的值
  * @retval None
  */
void PB_Port_04(uint16_t _reg,uint16_t _len,uint8_t* _res){

}
/**
  * @bried  写单个寄存器线圈寄存器
  * @note   None
  * @param  _reg：寄存器地址
  * @param  _state：待设置的线圈状态
  * @retval None
  */
void PB_Port_05(uint16_t _reg,PB_Reg_Coil_State _state){
    Set_GPIO_Port(_reg,_state==PB_Reg_Coil_State_On);
}
/**
  * @bried  写单个保持寄存器
  * @note   None
  * @param  _reg：寄存器地址
  * @param  _data：待设置的数据
  * @retval None
  */
void PB_Port_06(uint16_t _reg,uint16_t _data){
    if (_reg>1)return;
    if (gpio5_output_mode==0x00){//当前为GPIO模式
        DO5_GPIO_Port->CRH|=0x00000800;//设置CNF10位为10,10为复用推挽输出
        HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_3);
        gpio5_output_mode=0x01;
    }
    PrivateBus_Keep_Reg[_reg]=_data;
    if (_reg==0){
        TIM2->ARR=_data;//自动重装载值
    } else if (_reg==1){
        TIM2->CCR3=_data;//比较输出值
    }
}
/**
  * @bried  错误诊断
  * @note   08命令字作为拓展版挂载时，有私有主机代理08命令字记录功能
  * @param  _mode：子功能码
  * @param  _rx_data：接收到的数据
  * @param  _tx_data:待返回的数据段
  * @retval None
  */
//void PB_Port_08(uint16_t _mode,uint16_t _rx_data,uint8_t* _tx_data){
//    switch (_mode) {
////        case 0x0000:break;//回送诊断寄存器（Return Query Data）
////        case 0x0001:break;//重启通信链路（Restart Communications Option）
////        case 0x0002:break;//返回事件计数器（Return Diagnostic Register）
////        case 0x0003:break;//更改ASCII模式的波特率（Change ASCII Input Delimiter）
////        case 0x0004:break;//强制监听仅模式（Force Listen Only Mode）
//        case 0x000A:break;//清除计数器和诊断寄存器（Clear Counters and Diagnostic Register）
////        case 0x000B:break;//返回总消息计数（Return Bus Message Count）
////        case 0x000C:break;//返回总CRC错误计数（Return Bus Communication Error Count）
////        case 0x000D:break;//返回总异常响应计数（Return Bus Exception Error Count）
//        case 0x000E:break;//返回总报文计数（Return Slave Message Count）
////        case 0x000F:break;//返回总无响应计数（Return Slave No Response Count）
////        case 0x0010:break;//返回总写计数（Return Slave NAK Count）
////        case 0x0011:break;//返回总忙计数（Return Slave Busy Count）
////        case 0x0012:break;//返回总错误计数（Return Bus Character Overrun Count）
//        default:
//            break;
//    }
//}
/**
  * @bried  写多个线圈寄存器
  * @note   None
  * @param  _reg：寄存器地址
  * @param  _len：写寄存器数量
  * @param  _data：待设置的数据
  * @retval None
  */
void PB_Port_0F(uint16_t _reg,uint16_t _len,uint8_t const* _data){
    for (uint16_t i = 0; i < _len; ++i) {
        Set_GPIO_Port(_reg+i,((_data[i/8]&(0x01<<i))!=0));
    }
}
/**
  * @bried  写多个保持寄存器
  * @note   保持寄存器为16位，传入uint8需要手动解析为uint16，其中前面为高字节，后面为低字节。_len为uint8的数量
  * @param  _reg：寄存器地址
  * @param  _data：待写入的数据
  * @retval None
  */
void PB_Port_10(uint16_t _reg,uint16_t _len,uint8_t const* _data){
    for (int i = 0; i < _len; ++i) {
        if (_reg+i>1)return;
        PB_Port_06(_reg+i, __2U8TU16(_data[2*i+1],_data[2*i]));
    }
}


